home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2004 #11
/
Amiga Plus CD - 2004 - No. 11.iso
/
AmiSoft
/
Misc
/
emu
/
p-interp.lha
/
p-interp-0.5
/
Diskio.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-07
|
6KB
|
295 lines
/*
P-Code interpreter (to run the apple pascal system)
Copyright (C) 2000 Mario Klebsch
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
$Log: Diskio.c,v $
Revision 1.5 2001/06/07 19:57:53 mario
Implementierung vom Diskettenzugriff mittels read(), write() & lseek()
um Systeme ohne mmap() zu unterstützen.
Revision 1.4 2001/05/26 15:13:29 mario
Diverse kleine Fehler behoben, fehlende #includes, Labels ohne Statement
dahinter, ...
Revision 1.3 2001/05/21 19:06:48 mario
Mode-Parameter bei den Disk-IO-Routinen entfernt
Revision 1.2 2001/05/20 13:12:02 mario
CVS-Idents und Logs eingefügt
*/
#ident "$Id: Diskio.c,v 1.5 2001/06/07 19:57:53 mario Exp $";
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef USE_MMAP
#include <sys/mman.h>
#endif
#include "psystem.h"
#include "Memory.h"
#include "Diskio.h"
static int DskTable[16]={0,14,13,12,11,10,9,8,7,6,5,4,3,2,1,15};
static struct Unit
{
int Fd;
byte *Data;
size_t Size;
int RdOnly;
int *Translate;
} Units[MAX_UNIT];
void DiskRead(word Unit, word Addr, Integer AddrOffset,
word Len, word BlockNo)
{
int i;
size_t Offset = BlockNo*512;
int Track = BlockNo/8;
int Sector = (BlockNo&7)*2;
struct Unit *u;
assert(Unit<MAX_UNIT);
u=&Units[Unit];
if ( (u->Fd<0) && !u->Data )
{
IoError(9);
return;
}
if ((Offset+Len)>u->Size)
{
IoError(64);
return;
}
while (Len)
{
int Size=256;
int Sec=Sector;
if (Len<Size)
Size=Len;
if (u->Translate)
Sec=u->Translate[Sector];
if (u->Data)
for (i=0; i<Size; i++)
MemWrByte(Addr, AddrOffset+i,
u->Data[(Track*16+Sec)*256+i]);
else
{
char Buf[256];
if ( (lseek(u->Fd, (Track*16+Sec)*256, SEEK_SET) <0) ||
( read(u->Fd, Buf, Size) != Size) )
{
IoError(64);
return;
}
for (i=0; i<Size; i++)
MemWrByte(Addr, AddrOffset+i, Buf[i] );
}
AddrOffset +=Size;
Len-=Size;
Sector++;
if (Sector>=16)
{
Track++;
Sector=0;
}
}
IoError(0);
}
void DiskWrite(word Unit, word Addr, Integer AddrOffset,
word Len, word BlockNo)
{
int i;
size_t Offset = BlockNo*512;
int Track = BlockNo/8;
int Sector = (BlockNo&7)*2;
struct Unit *u;
assert(Unit<MAX_UNIT);
u=&Units[Unit];
if ( (u->Fd<0) && !u->Data )
{
IoError(9);
return;
}
else if (u->RdOnly)
{
IoError(16);
return;
}
else if ((Offset+Len)>u->Size)
{
IoError(64);
return;
}
while (Len)
{
int Size=256;
int Sec=Sector;
if (Len<Size)
Size=Len;
if (u->Translate)
Sec=u->Translate[Sector];
if (u->Data)
for (i=0; i<Size; i++)
u->Data[(Track*16+Sec)*256+i] =
MemRdByte(Addr, AddrOffset+i );
else
{
char Buf[256];
for (i=0; i<Size; i++)
Buf[i] = MemRdByte(Addr, AddrOffset+i );
if ( (lseek(u->Fd, (Track*16+Sec)*256, SEEK_SET) <0) ||
( write(u->Fd, Buf, Size) != Size) )
{
IoError(64);
return;
}
}
AddrOffset +=Size;
Len-=Size;
Sector++;
if (Sector>=16)
{
Track++;
Sector=0;
}
}
IoError(0);
}
void DiskClear(word Unit)
{
assert(Unit<MAX_UNIT);
IoError(0);
}
void DiskStat(word Unit)
{
struct Unit *u;
assert(Unit<MAX_UNIT);
u=&Units[Unit];
if ( (u->Fd<0) && !u->Data )
IoError(9);
else
IoError(0);
}
void DiskUmount(word Unit)
{
struct Unit *u;
assert(Unit<MAX_UNIT);
u=&Units[Unit];
if (u->Data)
{
#ifdef USE_MMAP
munmap(u->Data, u->Size);
#else
free(u->Data);
#endif
u->Data=NULL;
}
if (u->Fd>=0)
{
close(u->Fd);
u->Fd=-1;
}
}
int DiskMount(word Unit, const char *FileName, enum DiskMode Mode)
{
int fd;
struct stat buf;
struct Unit *u;
assert(Unit<MAX_UNIT);
u=&Units[Unit];
if ((fd=open(FileName,(Mode==ReadWrite)?O_RDWR:O_RDONLY))<0)
{
perror(FileName);
return(-1);
}
if (fstat(fd, &buf)<0)
{
perror(FileName);
close(fd);
return(-1);
}
DiskUmount(Unit);
u->Fd=fd;
u->Size=buf.st_size;
u->RdOnly=(Mode==ReadOnly);
u->Translate=NULL;
if ( (strlen(FileName)>4) &&
(strcmp(FileName+strlen(FileName)-4,".dsk")==0) )
u->Translate=DskTable;
#ifdef USE_MMAP
u->Data=mmap(NULL, u->Size,
(Mode==ReadOnly)?PROT_READ:PROT_READ|PROT_WRITE,
(Mode==Forget)?MAP_PRIVATE:MAP_SHARED,
u->Fd, 0);
close(Unit[Unit].Fd);
Unit[Unit].Fd=-1;
#else
if (Mode==Forget)
{
u->Data=malloc(u->Size);
assert(u->Data);
if (read(u->Fd,u->Data,u->Size) !=
u->Size)
{
perror(FileName);
free(u->Data);
u->Data=NULL;
close(u->Fd);
u->Fd=-1;
return(-1);
}
close(u->Fd);
u->Fd=-1;
}
#endif
return(0);
}
void DiskInit(void)
{
int i;
for (i=0; i<MAX_UNIT; i++)
{
Units[i].Data=NULL;
Units[i].Fd=-1;
}
}